package com.sdy.healthcode.web.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.healthcode.biz.dto.BayonetManageDTO;
import com.sdy.healthcode.biz.dto.PeopleActionDTO;
import com.sdy.healthcode.biz.dto.PersonnelEntryAndExitDTO;
import com.sdy.healthcode.biz.dto.ReportPeoplePassDTO;
import com.sdy.common.utils.StringUtil;
import com.sdy.healthcode.biz.model.BayonetManage;
import com.sdy.healthcode.biz.model.BuildingManage;
import com.sdy.healthcode.biz.model.ReportPeoplePass;
import com.sdy.common.model.Response;
import com.sdy.healthcode.biz.model.UserAction;
import com.sdy.healthcode.biz.service.BayonetManageService;
import com.sdy.healthcode.biz.service.BuildingManageService;
import com.sdy.healthcode.biz.service.ReportPeoplePassService;
import com.sdy.healthcode.biz.service.UserActionService;
import com.sdy.healthcode.biz.utils.CopyUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sdy.mvc.controller.BaseController;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 人员进出分析报表 前端控制器
 * </p>
 *
 * @author cgj
 * @since 2020-03-06
 */
@Slf4j
@RestController
@SuppressWarnings("unchecked")
@RequestMapping("/reportPeoplePass")
@Api(tags = "本院人员进出情况")
public class ReportPeoplePassController extends BaseController {
    @Autowired
    private ReportPeoplePassService reportPeoplePassService;
    @Autowired
    private UserActionService userActionService;
    @Autowired
    private BayonetManageService bayonetManageService;
    @Autowired
    private BuildingManageService buildingManageService;

    @GetMapping("/personnelManaPage")
    @ApiOperation(value = "本院人员进出情况", response = ReportPeoplePassDTO.class)
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "actionType", value = "进/出"),
            @ApiImplicitParam(name = "healthType", value = "体温状况(正常/发热)"),
            @ApiImplicitParam(name = "nameOrPhone", value = "姓名/联系方式"),
            @ApiImplicitParam(name = "starTime", value = "开始就时间"),
            @ApiImplicitParam(name = "endTime", value = "结束就时间"),
            @ApiImplicitParam(name = "department", value = "科室")
    })
    public Response personnelManaPage(String actionType, String healthType, String nameOrPhone, String startTime,
                                      String endTime, String department, Page<ReportPeoplePass> page) throws UnsupportedEncodingException {

        // 时间条件
        String creatTime = null;
        String overTime = null;

        if (StringUtil.isNotBlank(actionType)) {
            actionType = URLDecoder.decode(actionType, StandardCharsets.UTF_8.name());
        }
        if (StringUtil.isNotBlank(healthType)) {
            healthType = URLDecoder.decode(healthType, StandardCharsets.UTF_8.name());
        }
        if (StringUtil.isNotBlank(startTime)) {
            creatTime = startTime + " 00:00:00";
        }
        if (StringUtil.isNotBlank(endTime)) {
            overTime = endTime + " 23:59:59";
        }
        if (StringUtil.isNotBlank(nameOrPhone)) {
            nameOrPhone = URLDecoder.decode(nameOrPhone, StandardCharsets.UTF_8.name());
        }
        if (StringUtil.isNotBlank(department)) {
            department = URLDecoder.decode(department, StandardCharsets.UTF_8.name());
        }

        LambdaQueryWrapper<ReportPeoplePass> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtil.isNotBlank(actionType), ReportPeoplePass::getActionType, actionType)
                .eq(StringUtil.isNotBlank(healthType), ReportPeoplePass::getHealthType, healthType)
                .ge(StringUtil.isNotBlank(startTime), ReportPeoplePass::getRecordTime, creatTime)
                .le(StringUtil.isNotBlank(endTime), ReportPeoplePass::getRecordTime, overTime)
                .eq(StringUtil.isNotBlank(department), ReportPeoplePass::getDepartment, department);
        if (StringUtil.isNotBlank(nameOrPhone) && StringUtils.isNumeric(nameOrPhone)) {
            wrapper.like(ReportPeoplePass::getPhone, nameOrPhone);
        } else if (StringUtil.isNotBlank(nameOrPhone) && !StringUtils.isNumeric(nameOrPhone)) {
            wrapper.like(ReportPeoplePass::getName, nameOrPhone);
        }
        wrapper.orderByDesc(ReportPeoplePass::getRecordTime, ReportPeoplePass::getUserId);

        IPage<ReportPeoplePass> pageResult = reportPeoplePassService.page(page, wrapper);
        List<ReportPeoplePass> list = pageResult.getRecords();
        List<ReportPeoplePassDTO> reportPeoplePassDTOS = CopyUtil.batchClone(list, ReportPeoplePassDTO.class);
        List<Date> recordTimes = list.stream().map(ReportPeoplePass::getRecordTime).collect(Collectors.toList());
        for (int i = 0; i < recordTimes.size(); i++) {
            if (reportPeoplePassDTOS.get(i)!=null&&recordTimes.get(i)!=null) {
                reportPeoplePassDTOS.get(i).setTimeRecord(new SimpleDateFormat("HH:mm:ss").format(recordTimes.get(i)));
            }
        }
        return Response.success(new Page<ReportPeoplePassDTO>().setRecords(reportPeoplePassDTOS).setTotal(pageResult.getTotal())
                .setCurrent(pageResult.getCurrent()).setSize(pageResult.getSize()));
    }

    @GetMapping("/downloadStaff")
    @ApiOperation(value = "本院人员进出情况数据导出")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "actionType", value = "进/出"),
            @ApiImplicitParam(name = "healthType", value = "体温状况(正常/发热)"),
            @ApiImplicitParam(name = "nameOrPhone", value = "姓名/联系方式"),
            @ApiImplicitParam(name = "starTime", value = "开始就时间"),
            @ApiImplicitParam(name = "endTime", value = "结束就时间"),
            @ApiImplicitParam(name = "department", value = "科室")
    })
    public void downloadStaff(HttpServletResponse response, String actionType, String healthType, String nameOrPhone,
                              String startTime, String endTime, String department) throws UnsupportedEncodingException {

        // 时间条件
        String creatTime = null;
        String overTime = null;

        if (StringUtil.isNotBlank(actionType)) {
            actionType = URLDecoder.decode(actionType, StandardCharsets.UTF_8.name());
        }
        if (StringUtil.isNotBlank(healthType)) {
            healthType = URLDecoder.decode(healthType, StandardCharsets.UTF_8.name());
        }
        if (StringUtil.isNotBlank(startTime)) {
            creatTime = startTime + " 00:00:00";
        }
        if (StringUtil.isNotBlank(endTime)) {
            overTime = endTime + " 23:59:59";
        }
        if (StringUtil.isNotBlank(nameOrPhone)) {
            nameOrPhone = URLDecoder.decode(nameOrPhone, StandardCharsets.UTF_8.name());
        }
        if (StringUtil.isNotBlank(department)) {
            department = URLDecoder.decode(department, StandardCharsets.UTF_8.name());
        }

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
            String date = sdf.format(new Date());
            LambdaQueryWrapper<ReportPeoplePass> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StringUtil.isNotBlank(actionType), ReportPeoplePass::getActionType, actionType)
                    .eq(StringUtil.isNotBlank(healthType), ReportPeoplePass::getHealthType, healthType)
                    .ge(StringUtil.isNotBlank(startTime), ReportPeoplePass::getRecordTime, creatTime)
                    .le(StringUtil.isNotBlank(endTime), ReportPeoplePass::getRecordTime, overTime)
                    .eq(StringUtil.isNotBlank(department), ReportPeoplePass::getDepartment, department);
            if (StringUtil.isNotBlank(nameOrPhone) && StringUtils.isNumeric(nameOrPhone)) {
                wrapper.eq(ReportPeoplePass::getPhone, nameOrPhone);
            } else if (StringUtil.isNotBlank(nameOrPhone) && !StringUtils.isNumeric(nameOrPhone)) {
                wrapper.like(ReportPeoplePass::getName, nameOrPhone);
            }
            wrapper.orderByDesc(ReportPeoplePass::getRecordTime, ReportPeoplePass::getUserId);

            List<ReportPeoplePass> list = reportPeoplePassService.list(wrapper);
            List<ReportPeoplePassDTO> reportPeoplePassDTOS = CopyUtil.batchClone(list, ReportPeoplePassDTO.class);
            String fileName = "In and out of the hospital staff - " + date + ".xlsx";
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            EasyExcel.write(response.getOutputStream(), ReportPeoplePassDTO.class).sheet("本院人员进出数据导出表").doWrite(reportPeoplePassDTOS);
        } catch (Exception e) {
            log.error("本院人员进出数据导出表" + e.getMessage(), e);
        }
    }

    @GetMapping("/getPerAnalysis")
    @ApiOperation(value = "今日人员进出情况分析数据表", response = PersonnelEntryAndExitDTO.class)
    @ApiImplicitParams(
            @ApiImplicitParam(name = "typeId", value = "部门id")
    )
    public Response<Page<PersonnelEntryAndExitDTO>> getPerAnalysis(Integer typeId, String startTime, String endTime, Page page) {
        List<PersonnelEntryAndExitDTO> list = new ArrayList<>();
        if (typeId == null && StringUtil.isBlank(startTime) && StringUtil.isBlank(endTime)) {
            list = reportPeoplePassService.getEtryAndExitBase(page);
        } else if (typeId != null && StringUtil.isBlank(startTime) && StringUtil.isBlank(endTime)) {
            list = reportPeoplePassService.getEtryAndExitBaseByTypeId(typeId, page);
        } else if (typeId == null && StringUtil.isNotBlank(startTime) && StringUtil.isNotBlank(endTime)) {
            startTime = startTime + " 00:00:00";
            endTime = endTime + " 23:59:59";
            list = reportPeoplePassService.getEtryAndExitBaseByTime(startTime, endTime, page);
        } else if (typeId != null && StringUtil.isNotBlank(startTime) && StringUtil.isNotBlank(endTime)) {
            startTime = startTime + " 00:00:00";
            endTime = endTime + " 23:59:59";
            list = reportPeoplePassService.getEtryAndExitBaseByDouble(typeId, startTime, endTime, page);
        }
        Map<String, Object> typeEntryAndExit = new HashMap<>(16);
        for (int i = 0; i < list.size(); i++) {
            // 人员进入健康度数据处理
            String healthInNumAcc = getValue(list.get(i).getHealthInNum(), list.get(i).getInNum());
            list.get(i).setHealthInNumAcc(healthInNumAcc);
            // 人员出去健康度数据处理
            String healthOutNumAcc = getValue(list.get(i).getHealthOutNum(), list.get(i).getOutNum());
            list.get(i).setHealthOutNumAcc(healthOutNumAcc);
            // 进出次数数据处理
            int sumNum = (list.get(i).getInNum() == null ? 0 : list.get(i).getInNum()) + (list.get(i).getOutNum() == null ? 0 : list.get(i).getOutNum());
            list.get(i).setSumNum(sumNum);
            // 总体健康度数据处理
            String sumHealthNumAcc = getValue((list.get(i).getHealthInNum() == null ? 0 : list.get(i).getHealthInNum()) + (list.get(i).getHealthOutNum() == null ? 0 : list.get(i).getHealthOutNum()), list.get(i).getSumNum());
            list.get(i).setSumHealthNumAcc(sumHealthNumAcc);
        }
        typeEntryAndExit.put("everyDepartmentEntryAndExit", list);
        // 进入合计
        int inNum = 0;
        // 出去合计
        int outNum = 0;
        // 健康人员进入合计
        int healthInNum = 0;
        // 健康人员出去合计
        int healthOutNum = 0;
        if (!list.isEmpty()) {
            for (PersonnelEntryAndExitDTO one : list) {
                inNum += one.getInNum() == null ? 0 : one.getInNum();
                outNum += one.getOutNum() == null ? 0 : one.getOutNum();
                healthInNum += one.getHealthInNum() == null ? 0 : one.getHealthInNum();
                healthOutNum += one.getHealthOutNum() == null ? 0 : one.getHealthOutNum();
            }
        }
        // 人员进入健康度合计
        String healthInNumAcc = getValue(healthInNum, inNum);
        // 人员出去健康度合计
        String healthOutNumAcc = getValue(healthOutNum, outNum);
        // 进出总次数
        int sumNum = inNum + outNum;
        // 总体健康度数据
        String sumHealthNumAcc = getValue(healthInNum + healthOutNum, sumNum);
        PersonnelEntryAndExitDTO personnelEntryAndExitDTO = new PersonnelEntryAndExitDTO()
                .setInNumCount(inNum)
                .setOutNumCount(outNum)
                .setInHealthCountAcc(healthInNumAcc)
                .setOutHealthCountAcc(healthOutNumAcc)
                .setInAndOutCount(sumNum)
                .setSumHealthNumAcc(sumHealthNumAcc)
                .setType("总计")
                .setHealthInNum(healthInNum)
                .setHealthOutNum(healthOutNum);
        typeEntryAndExit.put("totalEntryAndExit", personnelEntryAndExitDTO);
        List<Map<String, Object>> setList = new ArrayList<>();
        setList.add(typeEntryAndExit);
        return Response.success(page.setRecords(setList));
    }

    public static String getValue(Integer dividend, Integer divisor) {
        if (divisor == null || divisor == 0) {
            return "0%";
        }
        if (dividend == null || dividend == 0) {
            return "0%";
        }
        DecimalFormat df = new DecimalFormat("0.0000");
        DecimalFormat cf = new DecimalFormat("0.00%");
        String format = cf.format(Float.parseFloat(df.format((float) dividend / divisor)));
        return format;
    }

    @GetMapping("/getPeopleAction")
    @ApiOperation(value = "今天行动轨迹", response = PeopleActionDTO.class)
    @ApiImplicitParams(
            @ApiImplicitParam(name = "id", value = "该人员id")
    )
    public Response<List<PeopleActionDTO>> getPeopleAction(Integer id, String recordDate) {
        LambdaQueryWrapper<UserAction> actionWrapper = new LambdaQueryWrapper<>();
        actionWrapper.eq(UserAction::getUserId, id).eq(UserAction::getRecordDate, recordDate).isNotNull(UserAction::getBayonetManageId).orderByDesc(UserAction::getRecordTime);
        List<UserAction> actionList = userActionService.list(actionWrapper);
        List<PeopleActionDTO> peopleActionDTOS = CopyUtil.batchClone(actionList, PeopleActionDTO.class);
        // 取出所有的卡点信息
        List<Integer> bayonetIds = actionList.stream().map(UserAction::getBayonetManageId).collect(Collectors.toList());
        List<BayonetManage> listBayonet = bayonetManageService.list(Wrappers.<BayonetManage>lambdaQuery().in(BayonetManage::getId, bayonetIds));
        List<BayonetManageDTO> bayonetManageDTOS = CopyUtil.batchClone(listBayonet, BayonetManageDTO.class);
        // 取出楼宇 楼层数据
        List<Integer> buildings = listBayonet.stream().map(BayonetManage::getBuilding).collect(Collectors.toList());
        List<Integer> floors = listBayonet.stream().map(BayonetManage::getFloor).collect(Collectors.toList());
        List<Integer> departments = listBayonet.stream().map(BayonetManage::getDepartment).collect(Collectors.toList());
        List<BuildingManage> listBuild = buildingManageService.list(Wrappers.<BuildingManage>lambdaQuery().in(BuildingManage::getId, buildings));
        List<BuildingManage> listFloor = buildingManageService.list(Wrappers.<BuildingManage>lambdaQuery().in(BuildingManage::getId, floors));
        List<BuildingManage> listDepartment = buildingManageService.list(Wrappers.<BuildingManage>lambdaQuery().in(BuildingManage::getId, departments));
        for (int i = 0; i < bayonetManageDTOS.size(); i++) {
            for (int j = 0; j < listBuild.size(); j++) {
                if (bayonetManageDTOS.get(i).getBuilding() != null && bayonetManageDTOS.get(i).getBuilding().equals(listBuild.get(j).getId())) {
                    bayonetManageDTOS.get(i).setBuildingStr(listBuild.get(j).getName());
                }
            }
            for (int k = 0; k < listFloor.size(); k++) {
                if (bayonetManageDTOS.get(i).getFloor() != null && bayonetManageDTOS.get(i).getFloor().equals(listFloor.get(k).getId())) {
                    bayonetManageDTOS.get(i).setFloorStr(listFloor.get(k).getName());
                }
            }
            for (int l = 0; l < listDepartment.size(); l++) {
                if (bayonetManageDTOS.get(i).getDepartment() != null && bayonetManageDTOS.get(i).getDepartment().equals(listDepartment.get(l).getId())) {
                    bayonetManageDTOS.get(i).setDepartmentStr(listDepartment.get(l).getName());
                }
            }
        }
        // 数据放到DTO
        for (int i = 0; i < peopleActionDTOS.size(); i++) {
            for (int j = 0; j < bayonetManageDTOS.size(); j++) {
                if (peopleActionDTOS.get(i).getBayonetManageId() != null && peopleActionDTOS.get(i).getBayonetManageId().equals(bayonetManageDTOS.get(j).getId())) {
                    peopleActionDTOS.get(i)
                            .setBuildingStr(bayonetManageDTOS.get(j).getBuildingStr())
                            .setFloorStr(bayonetManageDTOS.get(j).getFloorStr())
                            .setDepartmentStr(bayonetManageDTOS.get(j).getDepartmentStr())
                            .setBayonetName(bayonetManageDTOS.get(j).getBayonetName());
                }
            }
        }
        return Response.success(peopleActionDTOS);
    }
}
